#include <string>
#include <iostream>
#include <map> 
#include <list>
#include <fstream>
#include <algorithm>
#include <boost/unordered_map.hpp>
#include <boost/foreach.hpp>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include "threadpool.h"
#define QUEUE  256
using namespace std;
typedef boost::unordered_map<std::string, int> dict;
typedef boost::unordered_map<std::string, dict> long_dict;
std::map<int,string> *filelist;
std::map<int,string> *blacklist;
string dpath="sigdb_phish_clus/";
string spath="sigdb_cloud_clus/";
string outpath="res2/";
const int thres=238;
long_dict *dict_list;

int find_share(dict tsrc,string src_f,string dst_f)
{
    dict src=tsrc;

    dict dst=(*dict_list).at(dst_f);
    //cout<<src_f<<dst.size()<<endl; 
    int shared=0;
    BOOST_FOREACH(dict::value_type i, src) {
        if(dst.find(i.first) != dst.end())
        {
            shared=shared+min(src.at(i.first),dst.at(i.first));
        }
    }
   
    if (shared >= thres)
    {
	    cout<<"match blacklist "<<dst_f<<endl;
            return 1;
    }
    else
    {
        return 0;
    }
}

void dump_res(string target,dict res)
{   
    ofstream fout((outpath+target).c_str());
    BOOST_FOREACH(dict::value_type i, res) {  
        fout<<i.first<<"\n";
    } 
    fout.close();
}

void init_list(string dlist)
{
    std::map<int,string> tfilelist;
    ifstream in(dlist.c_str());
    string s;
    int lsize=0;

    while(getline(in,s)){
        //filelist[s]=0;
        tfilelist.insert ( std::pair<int,string>(lsize,s) );
        lsize=lsize+1;
    }
    in.close();

    for (std::map<int, string>::iterator iter=tfilelist.begin( ); iter != tfilelist.end( ); ++iter)
    {
        dict dst;
        string dst_f=(*iter).second;
        ifstream in((dpath+dst_f).c_str());
        string s;
    
        while(getline(in,s)){
            int i=s.find(',');
            string key=s.substr(0,i);
            string value=s.substr(i+1,s.size());
        //cout << key<<","<<value << endl;
            dst[key.c_str()]=atoi(value.c_str());

        }
        in.close();
        (*dict_list)[dst_f]=dst;
    }
}


void comp(void* args)
{

        dict result;
        std::list<int> mylist;
        //string target=(string)args;
        std::string *sp = static_cast<std::string*>(args);
        string target = *sp;
        delete sp;
        cout<<"tag is "<<target<<endl;
        dict src;
        ifstream in((spath+target).c_str());
        string s;
    
        while(getline(in,s)){
            int i=s.find(',');
            string key=s.substr(0,i);
            string value=s.substr(i+1,s.size());
        //cout << key<<","<<value << endl;
            src[key.c_str()]=atoi(value.c_str());

        }
        in.close();
        int flag=0;
        for (std::map<int, string>::iterator iter=(*blacklist).begin( ); iter != (*blacklist).end( ); ++iter)
        {
            string tmp=(*iter).second;

            int res=find_share(src,target,tmp);
            if (res==1)
            {
                result[tmp]=1;
                flag=1;

            }
        }
    
       // filelist.erase((*filelist.begin()).first);
        
        if (flag==1)
        {
            dump_res(target,result);
        }
}

int main(int argc, char* argv[])
{

   	 
    ifstream in(argv[1]);
    ifstream dlist(argv[2]);
    dict_list=new long_dict;
    filelist=new map<int,string>();
    blacklist=new map<int,string>();
    

    init_list(argv[2]);
    string s;
    int lsize=0;
    threadpool_t *pool;
    pool=threadpool_create(32, QUEUE, 0);

    while(getline(in,s)){
        //filelist[s]=0;
        (*filelist).insert ( std::pair<int,string>(lsize,s) );
        lsize=lsize+1;
    }
    in.close();
    lsize=0;

    while(getline(dlist,s)){
        //filelist[s]=0;
        (*blacklist).insert ( std::pair<int,string>(lsize,s) );
        lsize=lsize+1;
    }
    dlist.close();

    std::cout << "full dict size " <<(*dict_list).size()<< endl;
    std::cout << "full sdict size " <<(*filelist).size()<< endl;
    //second process
	int c=0;
	
    for (std::map<int, string>::iterator iter=(*filelist).begin( ); iter != (*filelist).end( ); ++iter)
    {
        string target=(*iter).second;
		c=c+1;
	//cout<<c<<"#"<<(*filelist).size()<<endl;
        void *vp = static_cast<void*>(new string(target.c_str()));
        while(threadpool_add(pool, &comp, vp, 0)!=0)
{
}
    }
    return 0;


}

